package xj.graph2d.tools;

import static xj.app.BaseApplicationFrame.getResourceString;

import java.awt.Cursor;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Point2D;
import java.util.Observer;

import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

import xj.app.DrawTool;
import xj.app.DrawToolkit;
import xj.graph2d.DrawShape;
import xj.graph2d.DrawShapeFactory;
import xj.graph2d.DrawShapeSearch;
import xj.graph2d.Group;
import xj.graph2d.SimpleDrawView;
import xj.graph2d.TextShape;
import xj.graph2d.app.DrawApp;
import xj.graph2d.app.StencilPanel;
import xj.graph2d.app.ToolPanel;

public class StencilTool  
  extends SimpleDrawTool {

  public StencilTool(DrawApp main, StencilPanel stencilPanel) {
    this.main = main;
    this.stencilPanel = stencilPanel;
  }

  @Override
  public void mouseLButtonPressed(Observer observer, Point p, int modifiers) {
    start(observer);
    selectedShape = null;
    mousePosition = p; 
    mouseButtonDown = true; 

    if (view != null) {
      Point2D cur = view.physicalToVirtual(p);

      DrawShape prevSelectedShape = doc.getSelectedShape();
      if (prevSelectedShape != null) {
	doc.setSelectedShape(null);
	canvas.repaintShape(prevSelectedShape, true);
      }
      DrawShapeSearch.Result result = doc.search(cur);
      if (result != null && 
	  result.shape != null &&
	  result.position != PointOutside) {
	selectedShape = result.shape;
	DrawShape parent = selectedShape.getParent();
	while (selectedShape != null) { 
	  if (!(selectedShape instanceof Group) &&	    
	      !(selectedShape instanceof TextShape &&
		!selectedShape.isDetachable())) {
	    break;
	  }
	  selectedShape = parent;
	  parent = selectedShape.getParent();
	}
      
	pos = result.position;
	doc.setSelectedShape(selectedShape);
      }

      canvas.repaint();
    }
  }

  @Override
  public void mouseMoved(Observer observer, Point p, int modifiers) {
    if (view == null) {
      start(observer);
    }
    if (view != null && 
	!mouseButtonDown) {
      Point2D cur = view.physicalToVirtual(p);
      DrawShapeSearch.Result result = doc.search(cur);
      if (result != null &&
	  result.shape != null &&
	  result.position != PointOutside) {
	canvas.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
      } else { 
	canvas.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
      }
    }
  }

  @Override
  public void mouseDragged(Observer observer, Point p, int modifiers) {
    Point p0 = mousePosition; 
    mousePosition = p;
    if (view != null && 
	mouseButtonDown &&
	p0 != null) {
      view.moveScrollPosition(p0.x - p.x, p0.y - p.y);
      canvas.repaint();
    }
  }

  @Override
  public void mouseLButtonReleased(Observer observer, Point p, int modifiers) { 
    mouseButtonDown = false; 
  }

  @Override
public void mouseEntered(Observer observer, Point p, int modifiers) {
    start(observer);
    selectedShape = null;
    mouseButtonDown = false; 
    canvas.repaint();
  }

  @Override
public void mouseExited(Observer observer, Point p, int modifiers) {
    mouseButtonDown = false; 
    if (main != null && 
	stencilPanel != null && 
	selectedShape != null) { 
      DrawToolkit toolkit = main.getDrawToolkit();
      String sname = selectedShape.getAnnotation();
      if (sname == null) { 
	sname = newStencilTempName();
	selectedShape.setAnnotation(sname);
      }

      SimpleDrawView view = main.getView();
      DrawTool tool = toolkit.getTool(sname);
      if (tool == null) { 
	//System.out.println("StencilTool: tool not found: " + sname);
	DrawShape proto = DrawShapeFactory.cloneDrawShape(selectedShape, view,
							  CLONE_PROTOTYPE_DRAW_ATTR, 
							  false);
	proto.setAnnotation(null);
	tool = ToolPanel.makeShapeTool(proto, sname, main);
	main.addTool(sname, tool);
      } else { 
	//System.out.println("StencilTool: tool found: " + sname);
      }

      view.setCurrentTool(tool);
    }
  }

  JPopupMenu popup = null;

  @Override
  public void popupTriggered(Observer observer, Point p, int modifiers) {
    mousePosition = p; 
    mouseButtonDown = false; 
    selectedShape = null;
    if (view != null) { 
      if (popup == null) { 
	popup = new JPopupMenu();
	ActionListener action = new ActionListener() { 
	    public void actionPerformed(ActionEvent e) { 
	      Object src = e.getSource();
	      if (src instanceof JMenuItem) {
		JMenuItem item = (JMenuItem) src;
		String cmd = item.getActionCommand();
		if ("edit".equals(cmd)) { 
		  stencilPanel.editCurrentStencil();
		} else if ("delete".equals(cmd)) { 
		  stencilPanel.deleteCurrentStencil();
		} else if ("new".equals(cmd)) { 
		  main.newStencil();
		}
	      }
	    }
	  };

	JMenuItem item = new JMenuItem(getResourceString("EditStencil.text"));
	item.setActionCommand("edit");
	item.addActionListener(action);
	popup.add(item);
	item = new JMenuItem(getResourceString("NewStencil.text"));
	item.setActionCommand("new");
	item.addActionListener(action);
	popup.add(item);
	item = new JMenuItem(getResourceString("DeleteStencil.text"));
	item.setActionCommand("delete");
	item.addActionListener(action);
	popup.add(item);
      }
      popup.show(view, p.x, p.y);
    }
  }

  String newStencilTempName() {
    String name = ""; 
    if (stencilPanel != null) { 
      String s = stencilPanel.getCurrentStencilName();
      if (s != null) {
	name = s + "-" + (count++);
      } else { 
	name = "Default1-" + (count++);
      }
    } else { 
      name = "Default2-" + (count++);
    }
    return name; 
  }

  protected DrawApp main; 
  protected StencilPanel stencilPanel;

  /**
   * Currently selected shape
   */
  protected DrawShape selectedShape;

  protected Point mousePosition; 
  protected int pos;
  protected boolean mouseButtonDown = false; 

  protected static int count = 1000; 

}
